using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using CreamX.Framework.Game;

using CreamX.Framework.Game.Components;
using CreamX.Framework.QuadTree;


namespace CreamX.Framework.SceneGraph
{
    public class CreamXSceneData
    {
        public string ContentRoot;

        private Camera2D _camera;

        public CreamXSceneData()
        {
            Materials = new List<CreamXMaterialBase>();
            Objects= new List<CreamXObject>();
            TemplateObjects = new List<CreamXObject>();
            Camera = new Camera2D();
            
            SpecialSceneItems = new List<ISceneItem>();
            AnimationData = new List<AnimationInfo>();

            QuadTree = new QuadTree<CreamXObject>(
             new FRect(new Vector2(0, 0),
                 new Vector2(100, 100)), 10);

        }
        
        public Camera2D Camera
        {
            get { return _camera; }
            set { _camera = value; }
        }
        
        public List<CreamXMaterialBase> Materials;
        
        public List<CreamXObject> TemplateObjects;
        
        public List<CreamXObject> Objects;
        
        internal List<ISceneItem> SpecialSceneItems;
        
        public List<AnimationInfo> AnimationData;
     
        //public List<CreamXTileSet> TileSets;

        //public TileGridManager TileGridManager;

        public void AddNewMaterial(CreamXMaterialBase material)
        {
            Materials.Add(material);
        }

        public CreamXMaterialBase GetMaterial(string name)
        {
            foreach (CreamXMaterialBase __mat in Materials)
            {
                if (__mat.Name == name)
                    return __mat;
            }
            return null;
        }

       

        public void RegisterObject(CreamXObject obj)
        {
            if (!obj.Template)
            {
                if (obj.Template)
                {
                    TemplateObjects.Add(obj);
                }
                else
                {
                    Objects.Add(obj);
                    obj.OnRegister();
                }
            }
        }

        public void RebuildQuadTree()
        {
            
            QuadTree= new QuadTree<CreamXObject>(
                new FRect(new Vector2(0, 0), 
                Camera.Size* Camera.Zoom), 10);

            foreach (CreamXObject __o in Objects)
            {
                try
                {
                    if (!__o.MarkForDelete && !__o.Template)
                    {
                        
                        QuadTreePositionItem<CreamXObject> __item =
                            new QuadTreePositionItem<CreamXObject>(__o, __o.Position,
                            new Microsoft.Xna.Framework.Vector2(__o.DisplayWidth * Camera.Zoom, __o.DisplayHeight * Camera.Zoom));
                        __o._positionItem = __item;

                        QuadTree.Insert(__item);

                    }
                }
                catch { }
            }
        }

        internal QuadTreePositionItem<CreamXObject> SetPositionItem(CreamXObject obj)
        {
            QuadTreePositionItem<CreamXObject> __item =
                new QuadTreePositionItem<CreamXObject>(obj, obj.Position - obj.Origin, 
                new Microsoft.Xna.Framework.Vector2(obj.DisplayWidth, obj.DisplayHeight));
            obj._positionItem = __item;
            
            QuadTree.Insert(__item);
            return __item;
        }
        public QuadTree<CreamXObject> QuadTree = null;
        public bool QuadTreeEnabled=true;
        public CreamXObject CreateClone(string name)
        {
            CreamXObject _newObject;
            
            foreach (CreamXObject __obj in TemplateObjects)
            {
                if (__obj.Name == name && __obj.Template)
                {
                    if (__obj is CreamXAnimatedObject)
                    {
                        _newObject = (CreamXAnimatedObject)__obj.Clone();
                    }
                    else
                        _newObject = (CreamXObject)__obj.Clone();
                    

                    _newObject.Template=false;
                    _newObject.Components.Clear();
                    foreach (CreamXComponent __comp in __obj.Components)
                    {
                        _newObject.AddComponent((CreamXComponent)__comp.Clone());
                    }

                    return _newObject;
                }
            }
            return null;
        }

        //This isnt gonna work really :S need to think of something else
        public CreamXObject GetInstance(string name)
        {
            foreach (CreamXObject __obj in Objects)
            {
                if (__obj.Name == name && !__obj.Template)
                {
                    CreamXObject __o = (CreamXObject)__obj;
                    return __o;
                }
            }
         
            return null;
        }

        public void InitializeScene()
        {
            try
            {
                CreamXGame.Instance.graphics.PreferredBackBufferWidth = (int)Camera.Size.X;
                CreamXGame.Instance.graphics.PreferredBackBufferHeight = (int)Camera.Size.Y;

                
                //Get the content manager
                foreach (CreamXMaterialBase __obj in Materials)
                {
                    try
                    {
                        __obj.Texture = CreamXGame.Instance.Content.Load<Texture2D>( GetFileNameWithoutExtension(__obj.MaterialFilename));
                    }
                    catch 
                    {
                        
                    }
                }
                /*foreach (CreamXTileSet __Ts in TileSets)
                {
                    __Ts.CurrentScene = this;
                    __Ts.Material.Init();
                    __Ts.Material.Texture = __Ts.Material.Texture;
                    __Ts.StartGame();
                }*/
                //if (TileGridManager != null)
                //    TileGridManager.Initialize();
                for (int i = 0; i < Objects.Count; i++)
                {
                    CreamXObject __obj = Objects[i];
                    if (!__obj.IsRegistered)
                        __obj.OnRegister();
                    if (__obj.Material == null)
                        continue;
                
                }
                foreach (CreamXObject __obj1 in TemplateObjects)
                {
                    if (__obj1.Material == null)
                        continue;
                    //if (!__obj1.IgnoreCameraPosition)
                    //    __obj1.Origin = new Microsoft.Xna.Framework.Vector2(__obj1.Material.Texture.Width / 2,
                    //        __obj1.Material.Texture.Height / 2);

                }
               
                //CreamXGame.Instance.graphics.ApplyChanges();
            }
            catch 
            {
                throw new Exception("File Not Found");
            }
        }

        private string GetFileNameWithoutExtension(string p)
        {
            return p.Substring(0, p.LastIndexOf("."));
        }

        internal void UnRegisterObject(CreamXObject __obj)
        {
            if (!__obj.Template)
            {
                foreach (CreamXComponent _c in __obj.Components)
                {
                    _c.OnUnRegister();
                }
                Objects.Remove(__obj);
                if (QuadTreeEnabled)
                {
                        __obj.QuadTreePositionItem.Delete();
                }
            }
        }

        public AnimationInfo GetAnimation(string p)
        {
            foreach (AnimationInfo __i in AnimationData)
            {
                if (__i.Name == p)
                    return __i;
            }
            return null;
        }

        public CreamXObject GetObject(string name)
        {
            
            foreach (CreamXObject __obj in Objects)
            {
                if (__obj.Name == name && !__obj.Template)
                {
                    if (__obj is CreamXAnimatedObject)
                    {
                        return __obj as CreamXAnimatedObject;
                    }
                    else
                        return __obj;
                }
            }
            return null;            
        }

        public CreamXObject GetTemplate(string p)
        {
            foreach (CreamXObject __obj in TemplateObjects)
            {
                if (__obj.Name == p && __obj.Template)
                {
                    if (__obj is CreamXAnimatedObject)
                    {
                        return __obj as CreamXAnimatedObject;
                    }
                    else
                        return __obj;
                }
            }
            return null;      
        }
    }

}
